home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / Main.bin / Security.java < prev    next >
Text File  |  1998-09-22  |  16KB  |  543 lines

  1. /*
  2.  * @(#)Security.java    1.58 98/07/01
  3.  *
  4.  * Copyright 1995-1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  * 
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. package java.security;
  16.  
  17. import java.util.*;
  18. import java.io.*;
  19. /**
  20.  * <p>This class centralizes all security properties and common security
  21.  * methods. One of its primary uses is to manage providers.
  22.  *
  23.  * @version 1.54 97/02/06
  24.  * @author Benjamin Renaud */
  25. public final class Security {
  26.  
  27.     /* Are we debugging? -- for developers */
  28.     static boolean debug = false;
  29.  
  30.     /* Are we displaying errors? -- for users */
  31.     static boolean error = true;
  32.  
  33.     /* The java.security properties */
  34.     private static Properties props; 
  35.  
  36.     /* Where we cache provider properties */
  37.     private static Properties propCache;
  38.  
  39.     /* A vector of providers, in order of priority */
  40.     private static Vector providers;
  41.  
  42.     static {
  43.     initialize();
  44.     }
  45.     
  46.     private static void initialize() {
  47.     props = new Properties();
  48.     propCache = new Properties();
  49.     providers = new Vector();
  50.  
  51.     File propFile = securityPropFile("java.security");
  52.     if (!propFile.exists()) {
  53.         System.err.println("security properties not found. using defaults.");
  54.         initializeStatic();
  55.     } else {
  56.         try {
  57.         FileInputStream fis = new FileInputStream(propFile);
  58.         InputStream is = new BufferedInputStream(fis);
  59.         props.load(is);
  60.         is.close();
  61.         } catch (IOException e) {
  62.         error("could not load security properties file from " + propFile +
  63.               ". using defaults.");
  64.         initializeStatic();
  65.         }
  66.     }
  67.     loadProviders();
  68.     }
  69.  
  70.     /* 
  71.      * Initialize to default values, if <java.home>/lib/java.security
  72.      * is not found.
  73.      */
  74.     private static void initializeStatic() {
  75.     props.put("security.provider.1", "sun.security.provider.Sun");
  76.     props.put("system.scope","sun.security.provider.IdentityDatabase");
  77.     }
  78.  
  79.     /**
  80.      * Don't let anyone instantiate this. 
  81.      */
  82.     private Security() {
  83.     }
  84.  
  85.     /**
  86.      * Loops through provider declarations, which are expected to be
  87.      * of the form:
  88.      *
  89.      * security.provider.1=sun.security.provider.Sun
  90.      * security.provider.2=sun.security.jsafe.Jsafe
  91.      * etc.
  92.      *
  93.      * The order determines the default search order when looking for 
  94.      * an algorithm.
  95.      */
  96.     private static void loadProviders() {
  97.  
  98.     int i = 1;
  99.  
  100.     while(true) {
  101.  
  102.         String name = props.getProperty("security.provider." + i++);
  103.         if (name == null) {
  104.         break;
  105.  
  106.         } else {
  107.         Provider prov = Provider.loadProvider(name);
  108.         if (prov != null) {
  109.             /* This must manipulate the datastructure
  110.                directly, because going through addProviders
  111.                causes a security check to happen, which
  112.                sometimes will cause the security
  113.                initialization to fail with bad
  114.                consequences. */
  115.             providers.addElement(prov);
  116.         }
  117.         }
  118.     }
  119.     }
  120.  
  121.     static File securityPropFile(String filename) {
  122.     // maybe check for a system property which will specify where to
  123.     // look. Someday.
  124.     String sep = File.separator;
  125.     return new File(System.getProperty("java.home") + sep + "lib" + sep + 
  126.             "security" + sep + filename);
  127.     }
  128.  
  129.     /**
  130.      * Looks up providers, and returns the property mapping the key,
  131.      * if any. The order in which the providers are looked up is the
  132.      * provider-preference order, as specificed in the security
  133.      * properties file.
  134.      */
  135.     static String getProviderProperty(String key) {
  136.     
  137.     String prop = propCache.getProperty(key);
  138.     if (prop != null) {
  139.         return prop;
  140.     }
  141.  
  142.     for (int i = 0; i < providers.size(); i++) {
  143.         Provider prov = (Provider)providers.elementAt(i);
  144.         
  145.         prop = prov.getProperty(key);
  146.         if (prop != null) {
  147.         propCache.put(key, prop);
  148.         return prop;
  149.         }
  150.     }
  151.     return prop;
  152.     }
  153.  
  154.     /**
  155.      * We always map names to standard names
  156.      */
  157.     static String getStandardName(String alias, String engineType) {
  158.     return getProviderProperty("Alg.Alias." + engineType + "." + alias);
  159.     }
  160.  
  161.     /** 
  162.      * Gets a specified property for an algorithm. The algorithm name
  163.      * should be a standard name. See Appendix A in the <a href=
  164.      * "../guide/security/CryptoSpec.html#AppA">
  165.      * Java Cryptography Architecture API Specification & Reference </a> 
  166.      * for information about standard algorithm names.
  167.      * One possible use is by specialized algorithm parsers, which may map 
  168.      * classes to algorithms which they understand (much like Key parsers 
  169.      * do).
  170.      *
  171.      * @param algName the algorithm name.
  172.      *
  173.      * @param propName the name of the property to get.
  174.      * 
  175.      * @return the value of the specified property.  
  176.      */
  177.     public static String getAlgorithmProperty(String algName,
  178.                           String propName) {
  179.     return getProviderProperty("Alg." + propName + "." + algName);
  180.     }
  181.  
  182.     /** 
  183.      * Given an algorithm name, returns the name of PublicKey class
  184.      * capable of handling keys for that algorithm. The algorithm name
  185.      * should be a standard name. See Appendix A in the <a href=
  186.      * "../guide/security/CryptoSpec.html#AppA">
  187.      * Java Cryptography Architecture API Specification & Reference </a> 
  188.      * for information about standard algorithm names.
  189.      *
  190.      * @param algName the standard algorithm name for which to get
  191.      * a public key class name.
  192.      */
  193.     static String getPublicKeyClassName(String algName, String format) {
  194.  
  195.     String stdName = getStandardName(algName, "Key");
  196.  
  197.     if (stdName == null) {
  198.         stdName = algName;
  199.     }
  200.  
  201.     String formatAndAlg = "PublicKey." + format + "." + stdName;
  202.     return getProviderProperty(formatAndAlg);
  203.     }
  204.  
  205.  
  206.     /** Given an algorithm name, returns the name of PrivateKey class
  207.      * capable of handling keys for that algorithm. The algorithm name
  208.      * should be a standard name. See Appendix A in the <a href=
  209.      * "../guide/security/CryptoSpec.html#AppA">
  210.      * Java Cryptography Architecture API Specification & Reference </a> 
  211.      * for information about standard algorithm names.
  212.      */
  213.     static String getPrivateKeyClassName(String algName, String format) {
  214.  
  215.     String stdName = getStandardName(algName, "Key");
  216.  
  217.     if (stdName == null) {
  218.         stdName = algName;
  219.     }
  220.  
  221.     return getProviderProperty("PrivateKey." + format + "." + stdName);
  222.     }
  223.  
  224.     static String getEngineClassName(String algName,
  225.                      String engineType)
  226.     throws NoSuchAlgorithmException {
  227.     /* First get the standard name */
  228.     String stdName = getStandardName(algName, engineType);
  229.     
  230.     if (stdName == null) {
  231.         stdName = algName;
  232.     }
  233.  
  234.     Class impl = null;
  235.  
  236.     Enumeration enum = providers.elements();
  237.  
  238.     String classname = getProviderProperty(engineType + "." + stdName);
  239.  
  240.     if (classname != null) {
  241.         return classname;
  242.     }
  243.  
  244.     throw new NoSuchAlgorithmException("algorithm " + algName + 
  245.                        " not available.");
  246.     }
  247.  
  248.     /** Given an algorithm name, returns the name of Signature class
  249.      * capable of handling keys for that algorithm. The algorithm name
  250.      * should be a standard name. See Appendix A in the <a href=
  251.      * "../guide/security/CryptoSpec.html#AppA">
  252.      * Java Cryptography Architecture API Specification & Reference </a> 
  253.      * for information about standard algorithm names.
  254.      */
  255.     private static String getEngineClassName(String algName, String provider, 
  256.                          String engineType) 
  257.     throws NoSuchAlgorithmException, NoSuchProviderException {
  258.  
  259.     if (provider == null) {
  260.         return getEngineClassName(algName, engineType);
  261.     }
  262.  
  263.     /* First get the standard name */
  264.     String stdName = getStandardName(algName, engineType);
  265.     
  266.     if (stdName == null) {
  267.         stdName = algName;
  268.     }
  269.  
  270.     Provider prov = getProvider(provider);
  271.     if (prov == null) {
  272.         throw new NoSuchProviderException("no such provider: " +
  273.                         provider);
  274.     }
  275.     
  276.     String className = prov.getProperty(engineType + "." + stdName);
  277.     if (className == null) {
  278.         throw new NoSuchAlgorithmException("no such algorithm: " +
  279.                              algName + 
  280.                              " for provider " +
  281.                          provider);
  282.     }
  283.     return className;
  284.     }
  285.  
  286.     /**
  287.      * Adds a new provider, at a specified position. The position is
  288.      * the preference order in which providers are searched for
  289.      * requested algorithms. Note that it is not guaranteed that this
  290.      * preference will be respected. The position is 1-based, that is,
  291.      * 1 is most preferred, followed by 2, and so on. Sometimes it
  292.      * will be legal to add a provider, but only in the last position,
  293.      * in which case the <code>position</code> argument will be ignored. 
  294.      * 
  295.      * <p>If the given provider is installed at the requested position,
  296.      * the provider that used to be at that position, and all providers
  297.      * with a position greater than <code>position</code>, are shifted up
  298.      * one position (towards the end of the list of installed providers).
  299.      * 
  300.      * <p>A provider cannot be added if it is already installed.
  301.      *
  302.      * @param provider the provider to be added.
  303.      *
  304.      * @param position the preference position that the caller would
  305.      * like for this provider.
  306.      *
  307.      * @return the actual preference position in which the provider was 
  308.      * added, or -1 if the provider was not added because it is
  309.      * already installed.
  310.      *
  311.      * @see #getProvider
  312.      * @see #removeProvider 
  313.      */
  314.     public static int insertProviderAt(Provider provider, int position) {
  315.  
  316.     check();
  317.  
  318.     /* First check if the provider is already installed */
  319.     Provider already = getProvider(provider.getName());
  320.     if (already != null) {
  321.         return -1;
  322.     }    
  323.         
  324.     int size = providers.size();
  325.     if (position > size || position <= 0) {
  326.         position = size+1;
  327.     }
  328.  
  329.     providers.insertElementAt(provider, position-1);
  330.  
  331.     /* clear the prop caches */
  332.     propCache = new Properties();
  333.     
  334.     return position;
  335.     }
  336.  
  337.     /**
  338.      * Adds a provider to the next position available.
  339.      *
  340.      * @param provider the provider to be added.
  341.      *
  342.      * @return the preference position in which the provider was 
  343.      * added, or -1 if the provider was not added because it is
  344.      * already installed.
  345.      * 
  346.      * @see #getProvider
  347.      * @see #removeProvider
  348.      */
  349.     public static int addProvider(Provider provider) {
  350.     
  351.     return insertProviderAt(provider, providers.size() + 1);
  352.     }
  353.  
  354.     /**
  355.      * Removes the provider with the specified name.
  356.      *
  357.      * <p>When the specified provider is removed, all providers located
  358.      * at a position greater than where the specified provider was are shifted
  359.      * down one position (towards the head of the list of installed providers).
  360.      *
  361.      * <p>This method returns silently if the provider is not installed.
  362.      *
  363.      * @param name the name of the provider to remove.
  364.      *
  365.      * @see #getProvider
  366.      * @see #addProvider
  367.      */
  368.     public static void removeProvider(String name) {
  369.  
  370.     check();
  371.     
  372.     Provider provider = getProvider(name);
  373.  
  374.     if (provider != null) {
  375.         providers.removeElement(provider);
  376.     }
  377.     }
  378.  
  379.     
  380.     /**
  381.      * Returns all providers currently installed.
  382.      * 
  383.      * @return an array of all providers currently installed.
  384.      */
  385.     public static Provider[] getProviders() {
  386.     check();
  387.     Provider[] result = new Provider[providers.size()];
  388.     providers.copyInto(result);
  389.     return result;
  390.     }
  391.  
  392.     /**
  393.      * Returns the provider installed with the specified name, if
  394.      * any. Returns null if no provider with the speicified name is
  395.      * installed.
  396.      * 
  397.      * @param name the name of the provider to get.
  398.      * 
  399.      * @return the provider of the specified name.
  400.      *
  401.      * @see #removeProvider
  402.      * @see #addProvider
  403.      */
  404.     public static Provider getProvider(String name) {
  405.     check();
  406.     Enumeration enum = providers.elements();
  407.     while (enum.hasMoreElements()) {
  408.         Provider prov = (Provider)enum.nextElement();
  409.         if (prov.getName().equals(name)) {
  410.         return prov;
  411.         }
  412.     }
  413.     return null;
  414.     }
  415.  
  416.     private static boolean checkSuperclass(Class subclass, Class superclass) {
  417.     while(!subclass.equals(superclass)) {
  418.         subclass = subclass.getSuperclass();
  419.         if (subclass == null) {
  420.         return false;
  421.         }
  422.     }
  423.     return true;
  424.     }
  425.  
  426.     /*
  427.      * Return an object configured to implemented type. Provider can
  428.      * be null, in which case all providers will be searched in order
  429.      * of preference.
  430.      */
  431.     static Object getImpl(String algorithm, String type, String provider)
  432.     throws NoSuchAlgorithmException, NoSuchProviderException {    
  433.  
  434.     String className = getEngineClassName(algorithm, provider, type);
  435.  
  436.     try {
  437.         Class typeClass = Class.forName("java.security." + type);
  438.         Class cl = Class.forName(className);
  439.  
  440.         if (checkSuperclass(cl, typeClass)) {
  441.         return cl.newInstance();
  442.         } else {
  443.         throw new NoSuchAlgorithmException("class configured for " + 
  444.                            type + ": " + className + 
  445.                            " not a " + type);
  446.         }
  447.     } catch (ClassNotFoundException e) {
  448.         throw new NoSuchAlgorithmException("class configured for " + 
  449.                            type + "(provider: " + 
  450.                            provider + ")" + 
  451.                            "cannot be found.\n" + 
  452.                            e.getMessage());
  453.     } catch (InstantiationException e) {
  454.         throw new NoSuchAlgorithmException("class " + className + 
  455.                            " configured for " + type +
  456.                            "(provider: " + provider + 
  457.                            ") cannot be instantiated.\n" + 
  458.                            e.getMessage());
  459.     } catch (IllegalAccessException e) {
  460.         throw new NoSuchAlgorithmException("class " + className + 
  461.                            " configured for " + type +
  462.                            "(provider: " + provider +
  463.                            ") cannot be accessed.\n" + 
  464.                            e.getMessage());
  465.     }
  466.     }
  467.  
  468.     /**
  469.      * Gets a security property.
  470.      *
  471.      * @param key the key of the property being retrieved.
  472.      *
  473.      * @return the valeu of the security property corresponding to key.
  474.      */
  475.     public static String getProperty(String key) {
  476.     check();
  477.     return props.getProperty(key);
  478.     }
  479.  
  480.     /**
  481.      * Sets a security property.
  482.      *
  483.      * @param key the name of the property to be set.
  484.      *
  485.      * @param datum the value of the property to be set.
  486.      */
  487.     public static void setProperty(String key, String datum) {
  488.     check();
  489.     props.put(key, datum);
  490.     }
  491.  
  492.     private static void check() {
  493.     
  494.     SecurityManager security = System.getSecurityManager();
  495.     if (security != null) {
  496.         security.checkSecurityAccess("java");
  497.     }
  498.     }
  499.     
  500.     /**
  501.      * Print an error message that may be significant to a user.
  502.      */
  503.     static void error(String msg) {
  504.     if (debug) {
  505.         System.err.println(msg);
  506.     }
  507.     }
  508.  
  509.     /**
  510.      * Print an error message that may be significant to a user.
  511.      */
  512.     static void error(String msg, Throwable t) {
  513.     error(msg);
  514.     if (debug) {
  515.         t.printStackTrace();
  516.     }
  517.     }
  518.     
  519.     /**
  520.      * Print an debugging message that may be significant to a developer.
  521.      */
  522.     static void debug(String msg) {
  523.     if (debug) {
  524.         System.err.println(msg);
  525.     }
  526.     }
  527.  
  528.     /**
  529.      * Print an debugging message that may be significant to a developer.
  530.      */
  531.     static void debug(String msg, Throwable t) {
  532.     if (debug) {
  533.         t.printStackTrace();
  534.         System.err.println(msg);
  535.     }
  536.     }
  537.  
  538.     
  539.     
  540. }
  541.     
  542.  
  543.